本文联合作者:@至原 @汤志敏 @溪恒 @满霸 @寒蝉
kubernetes网络性能问题
kubernetes网络可分为Pod网络、服务网络、网络策略三个部分。Pod网络依据kubernetes网络模型连接集群中的Pod、Node到一个扁平的3层网络中,也是服务网络、网络策略实现的底座。服务网络在Pod网络的路径上添加负载均衡的能力支持Pod到service的访问。网络策略则通过状态防火墙功提供pod间的访问控制。
当前服务网络和网络策略多基于kernel协议栈的L3包过滤技术Netfilter框架实现,包括conntrack, iptables, nat, ipvs等。Netfilter作为2001年加入kernel的的包过滤技术,提供了灵活的框架和丰富的功能,也是Linux中应用最为广泛的包过滤技术。不过其在性能、扩展能力等方面也一直存在一些问题,例如iptables规则由于是线性结构存在更新慢、匹配慢问题,conntrack在高并发场景中性能下降快、连接表被打满的问题等等。Netfilter的这些问题也导致了服务网络、网络策略难以满足大规模的kubernetes集群和一些高性能场景的需求。
为解决服务网络、网络策略基于netfilter实现的性能问题,也有一些通过云上网络产品来实现的方法。例如由L4负载均衡实现服务网络、安全组实现网络策略。云上网络产品提供了丰富的网络功能和确定的SLA的保障,但因当前云网产品主要聚焦在IaaS层,其创建速度、配额等限制存在难以满足云原生场景的弹性、快速等需求。
Pod网络的实现依据是否经过kernel L3协议栈可分为两大类:经过L3协议栈的路由、Bridge等,bypass L3协议栈的IPVlan、 MacVlan,、直通等。经过L3协议栈的方案由于datapath中保留了完整的L3的处理,可兼容当前的服务网络、网络策略的实现,但因L3的逻辑较重这类方案性能较低。bypass L3协议栈的方案,由于datapath逻辑简单性能扩展性都较好,但存在较难实现服务网络、网络策略的问题。
综上,kubernetes网络在性能上的问题总结为如下几类:考虑kubenetes网络当前的现状,我们需要重新实现一种不依赖于Netfilter的轻量的服务网络、网络策略实现。一方面可以应用于IPVlan、MacVlan、直通等高性能Pod网络中、补齐其对服务网络、网络策略的支持,另一方面新的实现需要有更好的性能、扩展能力。
基于eBPF的方案
eBPF: 可编程的转发面
eBPF在kernel实现了一个基于寄存器的虚拟机,并定于了自己的64bit指令集。通过系统调用,我们可以加载一段编写好的eBPF程序到kernel,并在相应的事件发生触发运行。同时kernel也提供的相关验证机制,确保加载的eBPF程序其可以被安全的执行,避免对kernel产生破坏,导致painc, 安全隐患等风险。kernel当前在许多模块中增加了eBPF的支持,并定义了多种的eBPF程序类型。每种类型确定了其可以加载到kernel中的位置、可以调用的kernel helper函数、运行eBPF程序时传递的对象、以及对kernel对象的读写权限等。目前网络是eBPF应用较多也是发展较快的的子系统之一。从协议栈底层的网卡到上层的socket,均存在多种类型的eBPF的支持。
同时,针对当前netfilter的一些性能,社区也在基于eBPF实现一个新的名为bpfilter的包过滤技术https://lwn.net/Articles/755919/。从网络开发者的视角,eBPF相当于在kernel中提供了一种可编程的数据面,同时由kernel去保证程序的安全性。我们希望基于此实现一种高性能的服务网络和网络策略,同时应用于IPVlan, MacVlan, 直通等bypass L3的Pod网络。从而在kubernetes中提供一种综合性能较好的网络解决方案。
tc-ebpf:一种新的服务网络&网络策略实现
tc-ebpf位于Linux协议栈的L2层,可以hook网络设备的入、出双向流量到eBPF实现的datapath,基于tc-ebpf实现网络网络&网络策略优势有:hook在tc层,不依赖kernel的L3协议栈能力,可较容易的支持ipvlan、macvlan、直通等多种高性能网络模式;
可以读写skb_buff,kernel提供的helper函数功能丰富,较容易实现复杂的datapath。
规则的匹配、更新基于Hash,比线性操作的iptables规则性能高、扩展性好
datapath可编程。可在不重启、升级kernel的前提下,对datpath进行更新、优化
通过tc-ebpf构建服务网络&网络策略一般需要实现如下几个模块:
Conntrack是服务网络、网络策略的基础模块。egress, ingress流量均会先经过conntrack的处理,并生成容器流量的连接状态。LoadBalance+ReverseNat为服务网络的模块。LoadBalance为egress流量选择可用的endpoint,并将负载均衡信息同步到连接追踪信息中;ReverseNat为ingress流量查找LoadBalance信息并执行发向nat,修改源IP为cluster ip。
Policy模块基于Conntrack的连接状态,对于新连接应用用户定义的Policy规则。我们也调研了当前相关的社区一些实现,Cilium是基于eBPF技术构建kubernetes网络能力其中的佼佼者,使用eBPF实现了Pod网络、服务网络、网络策略等能力,但也发现cilium目前支持的网络模式没有很好的应用于公有云的场景。- vxlan封包模式:在封包解包过程中造成额外的性能损失,并且封包之后的UDP包不能利用tso等网卡offload性能优化
- linux路由模式:在一些虚拟化环境中不支持2层的路由协议,比如在阿里云上没办法通过路由协议打通不同机器的Pod IP段?
- cni chain: cilium当前支持的的cni chain的方式,可以对接veth的网络插件,但性能上的优化并不明显。
Terway With eBPF: 我们的方案
Terway是阿里云容器服务团队开源的高性能容器网络插件,支持使用阿里云的弹性网卡来实现的容器网络。使得容器网络和虚拟机网络在同一个网络平面,在不同主机之间容器网络通信时不会有封包等损失,不依赖于分布式路由也能让集群规模不受限于路由条目限制。我们和Terway合作,通过CNI chain的方式连接Terway和Cilium,进一步优化了Kubernetes的网络性能。
Terway作为CNI chain的第一个CNI,在阿里云VPC之上创建Pod网络连接Pod到VPC,提供高性能的容器网络通信。而Cilium作为第二个CNI,实现高性能的服务网络和网络策略。
IPVlan Based CNI Chain
综合单Node上Pod密度、性能等因素,Pod网络采用VPC的eni多ip特性,基于IPVlan L2的方式创建。
同时在Cilium中实现一种IPVlan模式的CNI chain mode,在terway创建创建的Pod网络基础上接入tc-eBPF的datapath,实现服务网络和网络策略。性能评估
网络性能评估主要与Terway当前三种网络模式对比:
本方案实现的Terway With eBPF(下列图中简称eBPF)模式性能测试结论:
Pod网络
tcp性能测试结果:
udp性能测试结果:
服务网络
service网络测试不同网络模型下的service network的转发性能和扩展能力。测试对比了pod网络,service为1,1000, 5000四种类型。测试工具采用ab、nginx,nginx配置为8核心。
网络策略
Terway的网络模式中仅有策略路由。本测试对比了两种模式在被测pod为1配置1个policy以及被测pod为120配置120个policy下的性能数据。测试工具为ab-nginx, nginx配置为8核心。
总结 & 后续
分析当前Kubernetes中网络(Pod网络、服务网络及网络策略)中的性能、扩展能力等问题。我们调研了kenrel eBPF技术及社区开源的eBPF容器方案Cilium,最后在阿里云上结合Terway,基于ENI多IP的网络特性实现了一种高性能容器网络方案。同时我们在cilium实现的IPVlan L2的CNI chain方案也已开源到Cilium社区。在当前方案中Host Namespace的服务网络和网络策略的实现仍然是由kube-proxy实现。目前主要考虑Host Namespace中的服务网络流量在集群流量中占比较小,且流量类型较为复杂(包括cluter ip、node port、extern ip等),由eBPF实现的优先级不高收益较小。tc-ebpf由于在Linux的L3之前,暂无还无法支持分片报文的重组。这会导致服务网络&网络策略的实现对分片报文失效,对于此,我们设计了redirect分片到L3协议栈重组重入eBPF的方案。不过考虑到kubernets集群大都部署在同类网络中,分片报文出现的概率相对较低,未在当前版本中实现。另外,cilium当前也在eBPF中增加了服务网络&网络策略对分片报文的支持 (https://github.com/cilium/cilium/pull/10264),目前该实现还存在无法分片报文乱序到底的问题。
展望
eBPF作为新技术为kerenl的网络转发面开发提供了巨大的可能性。我们目前的方案相当于在L2层实现了服务网络、网络策略,虽然在性能上相比基于netfilter的方案存在一定的提升,但实现的conntrack模块在网络上依然是一个不可忽视的开销。另一方面我们也在思考,在kubernetes的pod或node中的datapath上是否真的需要conntrack?是否可以基于socket的状态信息实现无负载开销的conntrack。基于此我们也在探索在socket层实现服务网络、网络策略的可能性。我们希望可以借助socket层的eBPF,构建一种开销极小conntrack,进而实现一种性能、扩展性更优的服务网络、网络策略方案。